// 自执行函数
(function()
{

	var EXTUTIL = Ext.util, EACH = Ext.each, TRUE = true, FALSE = false;

	// 构造函数
	EXTUTIL.Observable = function()
	{
		var me = this, e = me.events;
		if( me.listeners )
		{
			me.on(me.listeners);
			delete me.listeners;
		}
		me.events = e || {};
	};

	// ///////////////////////////////////////////////////////////////// start

	// events是以下的情况

	events =
	{
		'afterrender': new Ext.util.Event(),
		'resize': new Ext.util.Event()
	};

	// Event的listeners里:

	listeners =
	[
	    {
		    fireFn: fn,
		    scope: this,
		    fn: fn,
		    options: options
	    }
	];

	// 所以，总的数据结构如下：

	events =
	{
		'afterrender':
		{
			listeners:
			[
			    {
				    fireFn: fn,
				    scope: this,
				    fn: fn,
				    options: options
			    },
			    {
				    fireFn: fn,
				    scope: this,
				    fn: fn,
				    options: options
			    }
			]
		},
		'resize':
		{
			listeners:
			[
			    {
				    fireFn: fn,
				    scope: this,
				    fn: fn,
				    options: options
			    },
			    {
				    fireFn: fn,
				    scope: this,
				    fn: fn,
				    options: options
			    }
			]
		}
	};

	new Ext.Window(
	{
		height: 300,
		width: 300,
		listeners:
		{
			'afterrender': function()
			{

			},
			'resize': function()
			{

			},
			scope: this
		}
	});

	new Ext.Window(
	{
		height: 300,
		width: 300,
		listeners:
		{
			'afterrender':
			{
				fn: function()
				{
				},
				scope: this
			}
		}
	});

	// ///////////////////////////////////////////////////////////////// end

	EXTUTIL.Observable.prototype =
	{
		// private
		filterOptRe: /^(?:scope|delay|buffer|single)$/,

		fireEvent: function()
		{
			var a = Array.prototype.slice.call(arguments, 0), ename = a[0].toLowerCase(), me = this, ret = TRUE, ce = me.events[ename], cc, q, c;

			// 如果事件挂起了
			if( me.eventsSuspended === TRUE )
			{
				if( q = me.eventQueue )
				{
					q.push(a);
				}
			}
			else if( typeof ce == 'object' )
			{
				// 如果设置了enableBubble()
				if( ce.bubble )
				{
					if( ce.fire.apply(ce, a.slice(1)) === FALSE )
					{
						return FALSE;
					}
					c = me.getBubbleTarget && me.getBubbleTarget();
					if( c && c.enableBubble )
					{
						cc = c.events[ename];
						if( !cc || typeof cc != 'object' || !cc.bubble )
						{
							c.enableBubble(ename);
						}
						return c.fireEvent.apply(c, a);
					}
				}
				else
				{
					a.shift();
					ret = ce.fire.apply(ce, a);
				}
			}
			return ret;
		},

		addListener: function( eventName, fn, scope, o )
		{
			var me = this, e, oe, ce;

			if( typeof eventName == 'object' )
			{
				o = eventName;
				for( e in o )
				{

					// e is ::: afterrender , resize , scope
					// oe is :: function , function , this

					// oe.fn || oe oe可能是对象{fn:function () {},scope:this}，也有可能是个function

					oe = o[e];
					if( !me.filterOptRe.test(e) )
					{

						// me.addListener('afterender', this, null);
						// 这里完全解析了listeners的用法

						me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
					}
				}
			}
			else
			{
				eventName = eventName.toLowerCase();
				ce = me.events[eventName] || TRUE;
				if( typeof ce == 'boolean' )
				{
					me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
				}
				ce.addListener(fn, scope, typeof o == 'object' ? o : {});
			}
		},

		removeListener: function( eventName, fn, scope )
		{
			var ce = this.events[eventName.toLowerCase()];
			if( typeof ce == 'object' )
			{
				ce.removeListener(fn, scope);
			}
		},

		/**
		 * purge: 净化；通便 删除所有的事件，这个太刺激了
		 */
		purgeListeners: function()
		{
			var events = this.events, evt, key;
			for( key in events )
			{
				evt = events[key];
				if( typeof evt == 'object' )
				{
					evt.clearListeners();
				}
			}
		},

		addEvents: function( o )
		{
			var me = this;
			me.events = me.events || {};
			if( typeof o == 'string' )
			{
				var a = arguments, i = a.length;
				while(i--)
				{
					me.events[a[i]] = me.events[a[i]] || TRUE;
				}
			}
			else
			{
				Ext.applyIf(me.events, o);
			}
		},

		hasListener: function( eventName )
		{
			var e = this.events[eventName.toLowerCase()];
			return typeof e == 'object' && e.listeners.length > 0;
		},

		// 挂起事件
		// 如果挂起两次 queueSuspended为true的话，那么将前面清空，false的话不清空
		suspendEvents: function( queueSuspended )
		{
			this.eventsSuspended = TRUE;
			if( queueSuspended && !this.eventQueue )
			{
				this.eventQueue = [];
			}
		},

		// 恢复事件
		resumeEvents: function()
		{
			var me = this, queued = me.eventQueue || [];
			me.eventsSuspended = FALSE;
			delete me.eventQueue;
			EACH(queued, function( e )
			{
				me.fireEvent.apply(me, e);
			});
		}
	};

	var OBSERVABLE = EXTUTIL.Observable.prototype;
	OBSERVABLE.on = OBSERVABLE.addListener;
	OBSERVABLE.un = OBSERVABLE.removeListener;

	EXTUTIL.Observable.releaseCapture = function( o )
	{
		o.fireEvent = OBSERVABLE.fireEvent;
	};

	function createTargeted( h, o, scope )
	{
		return function()
		{
			if( o.target == arguments[0] )
			{
				h.apply(scope, Array.prototype.slice.call(arguments, 0));
			}
		};
	};

	/**
	 * 如果在其buffer时间里多次触发同一事件监听函数，那么它只会执行最后一个触发的任务
	 */
	function createBuffered( h, o, l, scope )
	{
		l.task = new EXTUTIL.DelayedTask();
		return function()
		{
			l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
		};
	};

	// 只执行一次
	function createSingle( h, e, fn, scope )
	{
		return function()
		{
			// 删除监听
			e.removeListener(fn, scope);

			// 就执行这一次
			return h.apply(scope, arguments);
		};
	};

	/**
	 * 先延迟指定时间，然后去执行任务，每个任务一定会执行
	 */
	function createDelayed( h, o, l, scope )
	{
		return function()
		{
			var task = new EXTUTIL.DelayedTask(), args = Array.prototype.slice.call(arguments, 0);
			if( !l.tasks )
			{
				l.tasks = [];
			}
			l.tasks.push(task);
			task.delay(o.delay || 10, function()
			{
				l.tasks.remove(task);
				h.apply(scope, args);
			}, scope);
		};
	};

	// var event = new EXTUTIL.Event('man','work');
	// event.addListener(fn,this,{});

	/**
	 * obj 是Observable对象，总的来说，没什么用，主要是scope没有的话，垫个背 .name为事件名，貌似没用着，不知道为什么？？？？
	 */
	EXTUTIL.Event = function( obj, name )
	{
		this.name = name;
		this.obj = obj;
		this.listeners = [];
	};

	// comment ///////////////////////////////////////////////////////////// start

	// listeners数组中，会是这个样子

	listeners:
	[
	    {
		    fn: fn,
		    scope: scope,
		    option: {},
		    fireFn: h
	    },
	    {
		    fn: fn2,
		    scope: scope2,
		    option: {},
		    fireFn: h2
	    }
	]
	// 为什么存入了两个函数的引用(fn与fireFn) 答：fn是为了遍历相同的，fireFn则是执行时的函数
	// findListener时，是：scope === scope && fn === fn
	// 执行时，会是这个样子 fireFn.apply(scope || obj || window,args);

	// comment ///////////////////////////////////////////////////////////// end

	EXTUTIL.Event.prototype =
	{
		addListener: function( fn, scope, options )
		{
			var me = this, l;
			scope = scope || me.obj;

			// 如果listeners中不存在fn与scope都与当前要监听的相同，那么就添加

			if( !me.isListening(fn, scope) )
			{
				l = me.createListener(fn, scope, options);

				// 如果当前监听函数正在被触发，那么叫拷贝一份来添加，防止两个函数同时调用一个函数
				if( me.firing )
				{
					me.listeners = me.listeners.slice(0);
				}
				me.listeners.push(l);
			}
		},

		createListener: function( fn, scope, o )
		{
			o = o || {};
			scope = scope || this.obj;
			var l =
			{
				fn: fn,
				scope: scope,
				options: o
			}, h = fn;
			if( o.target )
			{
				// Only call the handler if the event was fired on the target Observable, not if the event was bubbled up from a child Observable.
				h = createTargeted(h, o, scope);
			}
			if( o.delay ) // 延迟执行，o.delay为延迟执行的毫秒数
			{
				h = createDelayed(h, o, l, scope);
			}
			if( o.single )
			{
				h = createSingle(h, this, fn, scope);
			}
			if( o.buffer )
			{
				h = createBuffered(h, o, l, scope);
			}
			l.fireFn = h;
			return l;
		},

		// 获得this.listeners中已经存在的fn与scope的监听
		findListener: function( fn, scope )
		{
			var list = this.listeners, i = list.length, l;

			scope = scope || this.obj;

			// 倒着找，先找到的概率比较大
			while(i--)
			{
				l = list[i];
				if( l )
				{
					if( l.fn == fn && l.scope == scope )
					{
						return i;
					}
				}
			}
			return -1;
		},

		// 找到的话，为true，找不到为false
		isListening: function( fn, scope )
		{
			return this.findListener(fn, scope) != -1;
		},

		removeListener: function( fn, scope )
		{
			var index, l, k, me = this, ret = FALSE;
			if( (index = me.findListener(fn, scope)) != -1 )
			{
				if( me.firing )
				{
					me.listeners = me.listeners.slice(0);
				}
				l = me.listeners[index];

				// 如果有正在执行的taks，则将task灭掉
				// 单个task
				if( l.task )
				{
					l.task.cancel();
					delete l.task;
				}

				// 多个task
				k = l.tasks && l.tasks.length;
				if( k )
				{
					while(k--)
					{
						l.tasks[k].cancel();
					}
					delete l.tasks;
				}

				me.listeners.splice(index, 1);
				ret = TRUE;
			}
			return ret;
		},

		// Iterate to stop any buffered/delayed events
		clearListeners: function()
		{
			var me = this, l = me.listeners, i = l.length;
			while(i--)
			{
				me.removeListener(l[i].fn, l[i].scope);
			}
		},

		fire: function()
		{
			var me = this, listeners = me.listeners, len = listeners.length, i = 0, l;

			if( len > 0 )
			{
				me.firing = TRUE;
				var args = Array.prototype.slice.call(arguments, 0);
				for( ; i < len; i++ )
				{
					l = listeners[i];
					if( l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE )
					{
						return (me.firing = FALSE);
					}
				}
			}
			me.firing = FALSE;
			return TRUE;
		}

	};
})();
